﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Drawing;

namespace ProgNetExtensions.Security
{
    public class SecurityInfo
    {
        public static Image LockImage { get; set; }
        public static event EventHandler SecurityChanged;
        public static void PerformSecurityChanged()
        {
            if (SecurityChanged != null)
            {
                SecurityChanged(null, EventArgs.Empty);
            }
        }
        
        private static DataTable _SecurityTable;
        public static DataTable SecurityTable
        {
            get { return _SecurityTable; }
            set
            {
                _SecurityTable = value;
                CreateDictionary();
                PerformSecurityChanged();
            }
        }
        public static string NameColumn
        {
            get;
            set;
        }
        public static string ParentColumn
        {
            get;
            set;
        }
        public static string VisibleColumn
        {
            get;
            set;
        }
        public static string EnabledColumn
        {
            get;
            set;
        }
        public static object TrueValue
        {
            get;
            set;
        }
        public static object FalseValue
        {
            get;
            set;
        }
        private static bool IsSecuritySet
        {
            get
            {
                if (SecurityTable != null)
                {
                    if (NameColumn.IsNotEmpty() && SecurityTable.Columns.Contains(NameColumn) &&
                       VisibleColumn.IsNotEmpty() && SecurityTable.Columns.Contains(VisibleColumn) &&
                       EnabledColumn.IsNotEmpty() && SecurityTable.Columns.Contains(EnabledColumn) &&
                       TrueValue != null &&
                       FalseValue != null &&
                       !TrueValue.Equals(FalseValue))
                    {
                        return true;
                    }
                }
                return false;
            }
        }

        private static void CreateDictionary()
        {
            AllSecurityInfo.Clear();
            if (IsSecuritySet)
            {
                foreach (DataRow row in SecurityTable.Rows)
                {
                    string name = row[NameColumn].AsString();
                    string parent = null;
                    
                    if (ParentColumn.IsNotEmpty() && 
                        SecurityTable.Columns.Contains(ParentColumn))
                        parent = row[ParentColumn].AsString();

                    bool enabled = row[EnabledColumn].Equals(TrueValue);
                    bool visible = row[VisibleColumn].Equals(TrueValue);

                    SetSecurityInfo(name, parent, enabled, visible);
                }
            }
        }
        private static Dictionary<string, SecurityInfo> AllSecurityInfo = new Dictionary<string, SecurityInfo>();

        public static SecurityInfo GetSecurityInfo(string name)
        {
            if (AllSecurityInfo.ContainsKey(name))
            {
                return AllSecurityInfo[name];
            }
            return null;
        }
        private static void SetSecurityInfo(string name, string parent, bool enable, bool visible)
        {
            SecurityInfo info = GetSecurityInfo(name);
            if (info == null)
            {
                info = new SecurityInfo(name, parent);
                AllSecurityInfo.Add(name, info);
            }
            info.Visible = visible;
            info.Enabled = enable;
        }
        public static void SetEnabled(string name, bool value)
        {
            if (AllSecurityInfo.ContainsKey(name))
            {
                AllSecurityInfo[name].Enabled = value;
            }
        }
        
        private bool _Enabled = true;
        private bool _Visible = true;
        private string _Name;
        
        public string Name
        {
            get { return _Name; }
        }
       
        public bool Enabled
        {
            get
            {
                if (Parent != null)
                {
                    if (!Parent.Enabled)
                        return false;
                }
                return _Enabled;
            }
            set
            {
                _Enabled = value;
                if (IsSecuritySet)
                {
                    DataRow row = SecurityTable.SelectFirstRow(NameColumn + " = " + Name.EscapeSql());
                    if (row != null)
                    {
                        row[EnabledColumn] = (value ? TrueValue : FalseValue);
                    }
                }
                if (!value)
                    LockChildren();
            }
        }
        public bool Visible
        {
            get
            {
                if (Parent != null)
                {
                    if (!Parent.Visible)
                        return false;
                }
                return _Visible;
            }
            set
            {
                _Visible = value;
                if (IsSecuritySet)
                {
                    DataRow row = SecurityTable.SelectFirstRow(NameColumn + " = " + Name.EscapeSql());
                    if (row != null)
                    {
                        row[VisibleColumn] = (value ? TrueValue : FalseValue);
                    }
                }
                if (!value)
                    HideChildren();
            }
        }



        private void HideChildren()
        {
            if (_ChildElements != null)
            {
                foreach (SecurityInfo child in ChildElements)
                {
                    child.Visible = false;
                }
            }
        }

        private SecurityInfo(string name, string parent)
        {
            _Name = name;
            if (parent.IsNotEmpty())
            {
                Parent = GetSecurityInfo(parent);
                if (Parent != null)
                {
                    Parent.ChildElements.Add(this);
                }
                else
                {
                    Parent = new SecurityInfo(parent, "");
                }
            }
        }

        private void LockChildren()
        {
            if (_ChildElements != null)
            {
                foreach (SecurityInfo child in ChildElements)
                {
                    child.Enabled = false;
                }
            }
        }
        
        private List<SecurityInfo> _ChildElements;
        public List<SecurityInfo> ChildElements
        {
            get
            {
                if (_ChildElements == null)
                    _ChildElements = new List<SecurityInfo>();
                return _ChildElements;
            }
        }

        public SecurityInfo Parent
        {
            get;
            set;
        }

    }
}
